package persistence;


import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.sql.DataSource;

/**
 *
 * @author Sobrenombre
 */
public class SqlConnector {
    private static final int SINGLECONNECTIONMODE = 1;
    private static final int POOLCONNECTIONMODE = 2;
    private static Connection connectionPool;
    private int connectionMode  = SINGLECONNECTIONMODE;

    private Context context;
    private DataSource dataSource;
    private Connection connection;
    private Statement stmt;
    private PreparedStatement pstmt; //Preparsea la consulta y la manda al server. Luego la puedo usar repetidamente cambiando el "?" por parametros (evita sql injection)
    private CallableStatement cstmt;

    private String resourceName = "jdbc/dlc_motor"; //{java:comp/env/]jdbc/<dataSource>
    private String driverName = "com.mysql.jdbc.Driver";  //com.mysql.jdbc.Driver
    private String url = "jdbc:mysql://localhost:3306/dlc_motor"; //jdbc:mysql://<host>:<port>/<db>
    private String usr = "root";
    private String pwd = "infernal999";
//    private String pwd = "R00Tme";

    private void setContext() throws Exception{
        
        if (dataSource == null){
            if (resourceName == null) throw new Exception ("SQLManager ERROR: Resource name nulo");

            context = new InitialContext();
            dataSource = (DataSource) context.lookup(resourceName);
        }
    }

    public void connect() throws Exception{
        if (connectionMode == SINGLECONNECTIONMODE){
            if (this.connection == null){
                Class.forName(driverName);
                this.connection = DriverManager.getConnection(url, usr, pwd);
            }
        }else{
            if(connectionPool == null){
                setContext();
                connectionPool = dataSource.getConnection();
            }

        }
    }

    public void disconnect() throws Exception{
        if (this.getConnection() != null){
            getConnection().close();
        }
    }

    public void reconnect() throws Exception{
        disconnect();
        connect();
    }

    public boolean executeStatement(String cadena) throws SQLException{
        stmt = getConnection().createStatement();

        return stmt.execute(cadena);
    }
    public ResultSet executeStatementQuery(String cadena) throws SQLException{
        stmt = getConnection().createStatement();
        ResultSet rs = stmt.executeQuery(cadena);

        return rs;
    }

    
    public boolean executeCallableStatement() throws SQLException{
        return cstmt.execute(); //OJO EL boolean que retorno es para saber si tengo un result set....
    }

    public ResultSet executePreparedStatement() throws SQLException{
        ResultSet rs = pstmt.executeQuery();
        return rs;
    }

    public boolean isConnected() throws SQLException{
        if (getConnection() != null) return !getConnection().isClosed();
        return false;
    }

    public PreparedStatement setPreparedStatement(String query) throws SQLException{
        return pstmt = getConnection().prepareStatement(query);

    }

    /**
     * Recibe cadena con formato tipo: {? = call function(?,?,?)}
     * donde el primer ? representa el parámetro de salida
     * y los otros son ejemplos de parámetros de entrada que recibe la función
     * @param query
     * @return CallableStatement
     * @throws java.sql.SQLException
     */
    public CallableStatement setCallableStatement (String query) throws SQLException{        
        return cstmt = getConnection().prepareCall(query);
    }

    public Connection getConnection() throws SQLException{
        if(connectionMode == SINGLECONNECTIONMODE){
            if(connection == null){
                try {
                    Class.forName(driverName);
                    this.connection = DriverManager.getConnection(url, usr, pwd);
                } catch (ClassNotFoundException ex) {
                    Logger.getLogger(SqlConnector.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            return connection;
        }else{
            if(connectionPool.isClosed()){
                try {
                    setContext();
                    connectionPool = dataSource.getConnection();
                } catch (Exception ex) {
                    Logger.getLogger(SqlConnector.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            return connectionPool;
        }
    }

    
}

